package com.sciencep.pro.core.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.sciencep.pro.common.config.Constant;
import com.sciencep.pro.common.exception.CustomException;
import com.sciencep.pro.core.dao.ProBaseInfoMapper;
import com.sciencep.pro.core.domain.dto.dingding.DingUserDetailVO;
import com.sciencep.pro.core.domain.entity.ProBaseInfo;
import com.sciencep.pro.core.domain.entity.ProChangebase;
import com.sciencep.pro.core.domain.entity.ProcessInstance;
import com.sciencep.pro.core.domain.entity.ProjectUpdateTO;
import com.sciencep.pro.core.service.DingDingService;
import com.sciencep.pro.core.service.IProChangebaseService;
import com.sciencep.pro.core.service.IProcessInstanceService;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class DingDingServiceImpl implements DingDingService {

    @Autowired
    IProcessInstanceService processInstanceService;

    @Resource
    ProBaseInfoMapper proBaseInfoMapper;

    @Autowired
    IProChangebaseService proChangebaseService;

    @Value("${dingding.processing.create}")
    String dingdingCreateCode;

    @Value("${dingding.processing.update}")
    String dingdingUpdateCode;




    @Override
    public String getAccessToken(String appkey, String appsecret) throws CustomException, ApiException {

        log.info("DingDing获取token参数===> tokenappkey: {} ,appsecret: {}",appkey,appsecret);
        if(StringUtils.isEmpty(appkey)||StringUtils.isEmpty(appsecret)){
            throw new CustomException("参数错误");
        }
        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(appkey);
        request.setAppsecret(appsecret);
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client.execute(request);
        log.info("DingDing获取token接口返回===>{}",response.getBody());
        if(response.getErrcode().equals(0L)) {
            return response.getAccessToken();
        }else {
            throw new CustomException("获取钉钉accessToken失败");
        }

    }

    @Override
    public DingUserDetailVO getUserDetailByUserid(String accessToken, String userid) throws CustomException, ApiException {

        log.info("DingDing获取用户详情参数===> accessToken: {} ,userid: {}",accessToken,userid);

        if(StringUtils.isEmpty(accessToken)||StringUtils.isEmpty(userid)){
            throw new CustomException("参数错误");
        }

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
        OapiUserGetRequest request = new OapiUserGetRequest();
        request.setUserid(userid);
        request.setHttpMethod("GET");
        OapiUserGetResponse response = client.execute(request, accessToken);
        log.info("DingDing获取用户详情接口返回===>{}",response.getBody());
        if(response.getErrcode().equals(0L)){
            DingUserDetailVO detailVO =new DingUserDetailVO();
            BeanUtils.copyProperties(response,detailVO);
            return detailVO;
        }else {
            throw new CustomException(response.getBody());
        }

    }

    @Override
    public List<OapiUserSimplelistResponse.Userlist> getUserSimplelist(OapiUserSimplelistRequest requestTO, String accessToken) throws CustomException, ApiException {

        if(null ==requestTO){
            throw new CustomException("参数错误");
        }
        log.info("DingDing获取部门下用户列表参数===> OapiUserSimplelistRequest {}", JSON.toJSONString(requestTO));
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/simplelist");

        requestTO.setHttpMethod("GET");
        OapiUserSimplelistResponse response = client.execute(requestTO, accessToken);
        log.info("DingDing获取部门下用户列表接口返回===>{}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return response.getUserlist();
        }else {
            throw new CustomException(response.getBody());
        }

    }

    @Override
    public List<Long> getDepartmentIdList(String id, String accessToken) throws CustomException, ApiException {

        log.info("DingDing子部门ID列表参数===> id: {} ,accessToken: {}",id,accessToken);

        if(id==null||accessToken==null){
            throw new CustomException("参数错误");
        }

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list_ids");
        OapiDepartmentListIdsRequest request = new OapiDepartmentListIdsRequest();
        request.setId(id);
        request.setHttpMethod("GET");
        OapiDepartmentListIdsResponse response = client.execute(request, accessToken);

        log.info("DingDing子部门ID列表接口返回===>{}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return response.getSubDeptIdList();
        }else {
            throw new CustomException(response.getBody());
        }
    }

    @Override
    public List<OapiDepartmentListResponse.Department> getDepartmentList(String accessToken, String lang, Boolean fetchChild, String id) throws CustomException, ApiException {


        if(StringUtils.isEmpty(accessToken)){
            throw new CustomException("参数错误");
        }
        if(null==lang){
            lang ="zh_CN";
        }

        log.info("DingDing部门列表参数===> id: {} ,accessToken: {} , fetch_child :{}",id,accessToken,fetchChild);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list");
        OapiDepartmentListRequest request = new OapiDepartmentListRequest();
        request.setId(id);
        request.setFetchChild(fetchChild);
        request.setLang(lang);
        request.setHttpMethod("GET");
        OapiDepartmentListResponse response = client.execute(request, accessToken);
        log.info("DingDing部门列表列表接口返回===>{}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return response.getDepartment();
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public OapiDepartmentGetResponse getDepartmentDetail(String id, String accessToken) throws CustomException, ApiException {


        if(StringUtils.isEmpty(accessToken)||StringUtils.isEmpty(id)){
            throw new CustomException("参数错误");
        }
        log.info("DingDing部门详情参数===> id: {} ,accessToken: {}",id,accessToken);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
        OapiDepartmentGetRequest request = new OapiDepartmentGetRequest();
        request.setId(id);
        request.setHttpMethod("GET");
        OapiDepartmentGetResponse response = client.execute(request, accessToken);
        log.info("DingDing部门详情===>{}",response.getBody());

        if(response.getErrcode().equals(0L)){

            return  response;
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public List<OapiRoleListResponse.OpenRoleGroup> getRoleList(Long size, Long offset, String accessToken) throws CustomException, ApiException {

        if(null ==size||null ==offset||null ==accessToken){
            throw new CustomException("参数错误");
        }
        log.info("DingDing角色列表参数===> size: {} , offset: {} ,accessToken: {}",size,offset,accessToken);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/role/list");
        OapiRoleListRequest request = new OapiRoleListRequest();
        request.setOffset(0L);
        request.setSize(10L);
        OapiRoleListResponse response = client.execute(request, accessToken);
        log.info("DingDing角色列表返回===> {}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return  response.getResult().getList();
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public OapiRoleListResponse.PageVo getRoleListPage(OapiRoleListRequest request, String accessToken) throws CustomException, ApiException {

        if(null ==request||null ==accessToken){
            throw new CustomException("参数错误");
        }
        log.info("DingDing角色列表参数===> size: {}",accessToken);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/role/list");
        OapiRoleListResponse response = client.execute(request, accessToken);
        log.info("DingDing角色列表返回===> {}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return  response.getResult();
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public OapiRoleSimplelistResponse.PageVo getRoleSimpleList(OapiRoleSimplelistRequest request, String accessToken) throws ApiException, CustomException {


        log.info("DingDing查询角色下用户列表参数===>request: {} ,accessToken: {}",request,accessToken);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/role/simplelist");
        OapiRoleSimplelistResponse response = client.execute(request, accessToken);

        log.info("DingDing查询角色下用户列表返回===> {}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return  response.getResult();
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public OapiReportListResponse.PageVo getReportList(OapiReportListRequest request, String accessToken) throws CustomException, ApiException {

        if(request==null){
            throw new CustomException("参数错误");
        }
        log.info("DingDing企业用户日志数据参数===> {}",JSON.toJSONString(request));


        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/report/list");

        OapiReportListResponse response = client.execute(request, accessToken);

        log.info("DingDing企业用户日志数据返回===>  {}",response.getBody());

        if(response.getErrcode().equals(0L)){
            return  response.getResult();
        }else {
            throw new CustomException(response.getMessage());
        }
    }

    @Override
    public OapiReportTemplateListbyuseridResponse.HomePageReportTemplateVo getReportTemplateListByUserId(String userid, Long offset, Long size, String accessToken) throws CustomException, ApiException {

        if(null ==size||null ==offset||null ==accessToken){
            throw new CustomException("参数错误");
        }
        log.info("DingDing获取用户可见的日志模板参数===> userid: {},offset: {},size: {}",userid,offset,size);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/report/template/listbyuserid");
        OapiReportTemplateListbyuseridRequest req = new OapiReportTemplateListbyuseridRequest();
        req.setUserid(userid);
        req.setOffset(offset);
        req.setSize(size);
        OapiReportTemplateListbyuseridResponse rsp = client.execute(req, accessToken);
        log.info("DingDing获取用户可见的日志模板数据返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getResult();
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public List<OapiAttendanceListResponse.Recordresult> getAttendanceList(OapiAttendanceListRequest req, String token) throws CustomException, ApiException {

        if(req==null){
            throw new CustomException("参数有误");
        }
        log.info("DingDing获取打卡结果状态参数参数===> {}",JSON.toJSONString(req));
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/attendance/list");

        OapiAttendanceListResponse rsp = client.execute(req,token);
        log.info("DingDing获取打开结果数据返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getRecordresult();
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public List<OapiAttendanceListRecordResponse.Recordresult> getAttendanceListRecord(OapiAttendanceListRecordRequest request, String token) throws CustomException, ApiException {
        if(request==null){
            throw new CustomException("参数有误");
        }
        log.info("DingDing查询打卡详情参数===> {}",JSON.toJSONString(request));


        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/attendance/listRecord");

        OapiAttendanceListRecordResponse rsp = client.execute(request,token);
        log.info("DingDing查询打卡数据返回===> {}",rsp.getBody());
        if("0".equals(rsp.getErrorCode())){
            JSONObject jsonObject =JSON.parseObject(rsp.getBody());
            return (List<OapiAttendanceListRecordResponse.Recordresult>) jsonObject.get("recordresult");
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public OapiAttendanceGetleavestatusResponse.LeaveStatusListVO getLeaveStatus(OapiAttendanceGetleavestatusRequest req, String token) throws CustomException, ApiException {

        if(req==null){
            throw new CustomException("参数有误");
        }
        log.info("DingDing查询请假状态参数参数===> {}",JSON.toJSONString(req));


        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getleavestatus");

        OapiAttendanceGetleavestatusResponse rsp = client.execute(req, token);
        log.info("DingDing查询请假状态数据返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getResult();
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public List<OapiSmartworkHrmEmployeeListResponse.EmpFieldInfoVO> getHrmEmployeeList(String userIdList, String fieldFilterList, String accessToken) throws CustomException, ApiException {

        if(StringUtils.isEmpty(userIdList)||StringUtils.isEmpty(accessToken)){
            throw new CustomException("参数有误");
        }
        log.info("DingDing获取员工花名册字段信息参数===> userid_list: {},field_filter_list: {}",userIdList,fieldFilterList);

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/list");
        OapiSmartworkHrmEmployeeListRequest req = new OapiSmartworkHrmEmployeeListRequest();
        req.setUseridList(userIdList);
        req.setFieldFilterList(fieldFilterList);
        OapiSmartworkHrmEmployeeListResponse rsp = client.execute(req, accessToken);
        log.info("DingDing获取员工花名册字段信息返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getResult();
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public OapiSmartworkHrmEmployeeQueryonjobResponse.PageResult getEmployeeQuerynjob(String statusList, Long offset, Long size, String token) throws CustomException, ApiException {

        if(StringUtils.isEmpty(statusList)||offset==null||size==null){
            throw new CustomException("参数有误");
        }
        log.info("DingDing获取在职员工ID参数===> {},status_list: {},offset: {},size:{}",statusList,size,token);
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/queryonjob");
        OapiSmartworkHrmEmployeeQueryonjobRequest req = new OapiSmartworkHrmEmployeeQueryonjobRequest();
        req.setStatusList(statusList);
        req.setOffset(offset);
        req.setSize(size);
        OapiSmartworkHrmEmployeeQueryonjobResponse rsp = client.execute(req , token);
        log.info("DingDing获取在职员工ID返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getResult();
        }else {
            throw new CustomException(rsp.getMessage());
        }

    }

    @Override
    public OapiSmartworkHrmEmployeeQuerydimissionResponse.Paginator getEmployeeDimission(Long offset, Long size, String token) throws CustomException, ApiException {
        if(offset==null||size==null){
            throw new CustomException("参数有误");
        }
        log.info("DingDing获取离职员工ID参数===> offset: {},size: {},token: {}",offset,size,token);
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/querydimission");
        OapiSmartworkHrmEmployeeQuerydimissionRequest req = new OapiSmartworkHrmEmployeeQuerydimissionRequest();
        req.setOffset(offset);
        req.setSize(size);
        OapiSmartworkHrmEmployeeQuerydimissionResponse rsp = client.execute(req , token);
        log.info("DingDing获取离职员工ID返回===> {}",rsp.getBody());
        if(rsp.getErrcode().equals(0L)){
            return  rsp.getResult();
        }else {
            throw new CustomException(rsp.getMessage());
        }
    }

    @Override
    public void createProcessInstance(ProBaseInfo proBaseInfo, String token, String userId) throws ApiException {

        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
        OapiProcessinstanceCreateRequest request = new OapiProcessinstanceCreateRequest();
        request.setProcessCode(dingdingCreateCode);
        List<OapiProcessinstanceCreateRequest.FormComponentValueVo> formComponentValues = new ArrayList<>();

        // 单行输入框
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo1 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo1.setName("项目名称");
        log.info("----"+proBaseInfo.getProName());
        vo1.setValue(proBaseInfo.getProName());
        formComponentValues.add(vo1);

        // 多行输入框
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo2 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo2.setName("项目编号");
        vo2.setValue(proBaseInfo.getProCode());
        log.info("----"+proBaseInfo.getProCode());

        formComponentValues.add(vo2);

        // 金额
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo3 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo3.setName("合同编号");
        log.info("----"+proBaseInfo.getContractCode());
        vo3.setValue(proBaseInfo.getContractCode());
        formComponentValues.add(vo3);

        // 金额
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo4 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo4.setName("归属分社");
        vo4.setValue(proBaseInfo.getBranchName());
        log.info("----"+proBaseInfo.getBranchName());

        formComponentValues.add(vo4);

        // 计算公式
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo5 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo5.setName("分社对接人");
        vo5.setValue(proBaseInfo.getContactName());
        formComponentValues.add(vo5);
        log.info("----"+proBaseInfo.getContactName());

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

        // 日期区间
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo9 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo9.setName("项目开始时间");
        log.info("----"+proBaseInfo.getProStartDay());

        vo9.setValue(formatter.format(proBaseInfo.getProStartDay()));
        formComponentValues.add(vo9);

        OapiProcessinstanceCreateRequest.FormComponentValueVo vo10 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo10.setName("项目结束时间");
        log.info("----"+proBaseInfo.getProEndday());

        vo10.setValue(formatter.format(proBaseInfo.getProEndday()));
        formComponentValues.add(vo10);

        request.setFormComponentValues(formComponentValues);
        request.setOriginatorUserId(userId);
        request.setDeptId(Long.valueOf(proBaseInfo.getDeptId()));
        request.setAgentId(867701593L);
        OapiProcessinstanceCreateResponse response = client.execute(request,token);
        if(response.getErrcode().equals(0L)){
            log.info(response.getBody());
            ProcessInstance processInstance =new ProcessInstance();
            processInstance.setInstanceId(response.getProcessInstanceId());
            processInstance.setObjId(proBaseInfo.getId().toString());
            processInstance.setStatus("NEW");
            processInstance.setType(1);
            processInstance.setInstanceName(proBaseInfo.getProName());
            processInstanceService.save(processInstance);
            proBaseInfoMapper.updateById(proBaseInfo.setProStatus(2));
        }
    }

    @Override
    public void createProjectUpdateProcessInstance(ProjectUpdateTO projectUpdateTO, String token, String userId) throws ApiException {

        DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
        OapiProcessinstanceCreateRequest request = new OapiProcessinstanceCreateRequest();
        request.setProcessCode(dingdingUpdateCode);
        List<OapiProcessinstanceCreateRequest.FormComponentValueVo> formComponentValues = new ArrayList<>();

        // 单行输入框
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo1 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo1.setName("变动概述");
        vo1.setValue(projectUpdateTO.getChangeDesc());
        formComponentValues.add(vo1);

        // 多行输入框
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo2 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo2.setName("项目周期变更");
        vo2.setValue(projectUpdateTO.getProDateChange());
        formComponentValues.add(vo2);

        // 金额
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo3 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo3.setName("节点周期变更");
        vo3.setValue(projectUpdateTO.getNodeDateChange());
        formComponentValues.add(vo3);

        // 金额
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo4 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo4.setName("新增人员");
        vo4.setValue(projectUpdateTO.getNewMember());
        formComponentValues.add(vo4);

        // 计算公式
        OapiProcessinstanceCreateRequest.FormComponentValueVo vo5 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
        vo5.setName("变更(延迟或缩短)人员");
        vo5.setValue(projectUpdateTO.getUpdateMember());
        formComponentValues.add(vo5);


        request.setFormComponentValues(formComponentValues);
        request.setOriginatorUserId(userId);
        try {
            request.setDeptId(Long.valueOf(projectUpdateTO.getDeptId()));
        }catch (Exception e){
            request.setDeptId(-1L);
        }
        request.setAgentId(867701593L);
        OapiProcessinstanceCreateResponse response = client.execute(request,token);
        if(response!=null&&response.getErrcode().equals(0L)) {
            ProcessInstance processInstance =new ProcessInstance();
            processInstance.setInstanceId(response.getProcessInstanceId());
            processInstance.setObjId(projectUpdateTO.getChangeNo());
            processInstance.setStatus("NEW");
            processInstance.setType(2);
            processInstance.setInstanceName("项目变更");
            processInstanceService.save(processInstance);
            proChangebaseService.update(new UpdateWrapper<ProChangebase>()
                    .eq("changeNo",projectUpdateTO.getChangeNo())
                    .set("changeStatus", Constant.ProChangeStatus.START));



        }
    }

    @Override
    public OapiProcessinstanceGetResponse.ProcessInstanceTopVo getProcessResult(String id, String token) throws ApiException, CustomException {

        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
        OapiProcessinstanceGetRequest request = new OapiProcessinstanceGetRequest();
        request.setProcessInstanceId(id);
        OapiProcessinstanceGetResponse response = client.execute(request,token);
        if(response==null||response.getProcessInstance()==null){
            throw new CustomException("审批钉钉接口出错");
        }
        return response.getProcessInstance();
    }


}
